﻿using BluetoothMachine.Enums;
using BluetoothMachine.Models;
using Prism.Mvvm;
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using System.IO;
using System.Collections.Generic;
using BluetoothMachine.Lucifer;
using BluetoothMachine.DeviceCommunications;

namespace BluetoothMachine.GlobalStatics
{
    [Attributes.Singleton]
    public class DeviceManagementGlobal : BindableBase
    {
        private ObservableCollection<DeviceConfigModel> _deviceList;

        public ObservableCollection<DeviceConfigModel> DeviceList
        {
            get { return _deviceList; }
            set { SetProperty(ref _deviceList, value); }
        }
        public List<ICommunication> ConnectList { get; set; }
        public DeviceManagementGlobal()
        {
            ConnectList = new List<ICommunication>();
            if (!File.Exists(FixedParameter.DevicePath)) File.WriteAllText(FixedParameter.DevicePath, JsonSerializer.Serialize(new ObservableCollection<DeviceConfigModel>()), System.Text.Encoding.UTF8);
            DeviceList = JsonSerializer.Deserialize<ObservableCollection<DeviceConfigModel>>(File.ReadAllText(FixedParameter.DevicePath, System.Text.Encoding.UTF8));
        }
        private object _obj = new object();
        public bool ConnectionTcp()
        {
            ConnectList.Clear();
            return Parallel.ForEach(DeviceList, (x, _parallelLoopState) =>
            {
                try
                {
                    ICommunication model = new CommTCP(x.Address, x.Port)
                    {
                        CommType = x.Port < 9910,
                        Index = x.SerialNumber,
                        Types = DeviceType.前扫码
                    };
                    model.Connection();
                    lock (_obj)
                    {
                        ConnectList.Add(model);
                    }
                }
                catch (Exception ex)
                {
                    log4net.LogManager.GetLogger("message").Error($"{x.Address} 打开失败 异常：{ex.Message}");
                    _parallelLoopState.Stop();
                }
            }).IsCompleted;
        }
        public void DisconnectTCP()
        {
            foreach (var item in ConnectList)
            {
                try
                {
                    item.Disconnect();
                }
                finally { }
            }
        }
        public void Save() => File.WriteAllText(FixedParameter.DevicePath, JsonSerializer.Serialize(DeviceList), System.Text.Encoding.UTF8);
        
        /// <summary>
        /// 生成IP地址
        /// </summary>
        /// <param name="startAddress">开始地址</param>
        /// <param name="startPort">开始端口</param>
        /// <param name="endAddress">结束地址</param>
        /// <param name="endPort">结束端口</param>
        public void AddDevices(string startAddress, string startPort, string endAddress, string endPort)
        {
            string[] str = new string[] { startAddress, startPort, endAddress, endPort };
            GenerateAddress(str, DeviceType.红外线,
                GetAddressPortInt(str),
                DeviceList);
        }

        #region 计算IP地址差与生成
        private void GenerateAddress(string[] str, DeviceType deviceType, CalculateWeighingAddress calculate, ObservableCollection<DeviceConfigModel> servers)
        {
            if (string.IsNullOrEmpty(str[0]) || string.IsNullOrEmpty(str[1]) || string.IsNullOrEmpty(str[2]) || string.IsNullOrEmpty(str[3]))
            {
                return;
            }
            if (calculate.IPLength == 0)
            {
                for (int i = 0; i <= calculate.PortLength; i++)
                {
                    servers.Add(new DeviceConfigModel()
                    {
                        Address = calculate.Address,
                        Port = calculate.StartPort + i,
                        DeviceTypes = deviceType,
                        SerialNumber = i + 1,
                    });
                }
                return;
            }
            for (int i = 0; i <= calculate.IPLength; i++)
            {
                servers.Add(
                    new DeviceConfigModel()
                    {
                        Address = $"{calculate.StrArray[0]}.{calculate.StrArray[1]}.{calculate.StrArray[2]}.{calculate.StartIP + i}",
                        Port = calculate.StartPort,
                        DeviceTypes = deviceType,
                        SerialNumber = i + 1,
                    });
            }
        }

        private CalculateWeighingAddress GetAddressPortInt(string[] str)
        {
            string[] strArray = str[0].Split('.');
            var obj = new CalculateWeighingAddress()
            {
                Address = str[0],
                StrArray = strArray,
                StartIP = Convert.ToInt32(strArray[3]),
                StartPort = Convert.ToInt32(str[1]),
                EndIP = Convert.ToInt32(str[2].Split('.')[3]),
                EndPort = Convert.ToInt32(str[3])
            };
            obj.IPLength = obj.EndIP - obj.StartIP;
            obj.PortLength = obj.EndPort - obj.StartPort;
            return obj;
        }

        private class CalculateWeighingAddress
        {
            /// <summary>
            /// IP地址
            /// </summary>
            public string Address { get; set; }
            /// <summary>
            /// 开始地址最后一位
            /// </summary>
            public int StartIP { get; set; }
            /// <summary>
            /// 结束地址最后一位
            /// </summary>
            public int EndIP { get; set; }
            /// <summary>
            /// 开始端口号
            /// </summary>
            public int StartPort { get; set; }
            /// <summary>
            /// 结束端口号
            /// </summary>
            public int EndPort { get; set; }
            /// <summary>
            /// IP差
            /// </summary>
            public int IPLength { get; set; }
            /// <summary>
            /// 端口号差
            /// </summary>
            public int PortLength { get; set; }
            /// <summary>
            /// 分割IP地址后的数组
            /// </summary>
            public string[] StrArray { get; set; }
        }
        #endregion
    }
}
